home *** CD-ROM | disk | FTP | other *** search
- .!****************************************************************************
- .!
- .! ANTIC PUBLISHING INC., COPYRIGHT 1985. REPRINTED BY PERMISSION.
- .!
- .! ** Professional GEM ** by Tim Oren
- .!
- .! Proff File by ST enthusiasts at
- .! Case Western Reserve University
- .! Cleveland, Ohio
- .! uucp : decvax!cwruecmp!bammi
- .! csnet: bammi@case
- .! arpa : bammi%case@csnet-relay
- .! compuserve: 71515,155
- .!
- .!****************************************************************************
- .!
- .!
- .!****************************************************************************
- .!
- .! Begin Part I
- .!
- .!****************************************************************************
- .!
- .PART I Windows
- .SH IN THE BEGINNING
- In GEM, creating a window and displaying it are two different functions. The
- creation function is called wind_create, and its calling sequence is:
- .FB wind_create()
- handle = wind_create(parts, xfull, yfull, wfull, hfull);
- .FE
- This function asks GEM to reserve space in its memory for a new window
- description, and to return a code or "handle" which you can use to refer to the
- window in the future. Valid window handles are positive integers; they are not
- memory pointers.
- .PP
- GEM can run out of window handles. If it does so, the value returned is
- negative. Your code should always check for this situation and ask the
- program's user to close some windows and retry if possible. Handle zero is
- special. It refers to the "desktop", which is predefined as light green (or
- gray) on the ST. Window zero is always present and may be used, but never
- deleted, by the programmer.
- .PP
- The xfull, yfull, wfull, and hfull parameters are integers which determine
- the maximum size of the window. Xfull and yfull define the upper left corner of
- the window, and wfull and hfull specify its width and height. (Note that all of
- the window coordinates which we use are in pixel units.)
- .PP
- GEM saves these values so that the program can get them later when processing
- FULL requests. Usually the best maximum size for a window is the entire
- desktop area, excepting the menu bar. You can find this by asking wind_get for
- the working area of the desktop (handle zero, remember):
- .FB wind_get()
- wind_get(0, WF_WXYWH, &xfull, &yfull, &wfull, &hfull);
- .FE
- Note that WF_WXYWH, and all of the other mnemonics used in this article, are
- defined in the GEMDEFS.H file in the ST Toolkit.
- .PP
- The parts parameter of wind_create defines what features will be included in
- the window when it is drawn. It is a word of single bit flags which indicate
- the presence/absence of each feature. To request multiple features, the flags
- are "or-ed" together. The flags' mnemonics and meanings are:
- .BO
- NAME - A one character high title bar at the top of the window.
- .EO
- .BO
- INFO - A second character line below the NAME.
- .EO
- .BO
- MOVER - This lets the user move the window around by "dragging" in the NAME
- area. NAME also needs to be defined.
- .EO
- .BO
- CLOSER - A square box at the upper left. Clicking this control point asks
- that the window be removed from the screen.
- .EO
- .BO
- FULLER - A diamond at upper right. Clicking this control point requests
- that the window grow to its maximum size, or shrink back down if it is already
- big.
- .EO
- .BO
- SIZER - An arrow at bottom right. Dragging the SIZER lets the user choose
- a new size for the window.
- .EO
- .BO
- VSLIDE - defines a right-hand scroll box and bar for the window. By dragging
- the scroll bar, the user requests that the window's "viewport" into the
- information be moved. Clicking on the gray box above the bar requests that
- the window be moved up one "page". Clicking below the bar requests a down page
- movement. You have to define what constitutes a page or line in the
- context of your application.
- .EO
- .BO
- UPARROW - An arrow above the right scroll bar. Clicking here requests that
- the window be moved up one "line". Sliders and arrows almost always appear
- together.
- .EO
- .BO
- DNARROW - An arrow below the right scroll bar. Requests that window be
- moved down a line.
- .EO
- .BO
- HSLIDE - These features are the horizontal equivalent of the RTARROW
- above. They appear at the bottom of the window. Arrows LFARROW usually
- indicate "character" sized movement left and right. "Page" sized
- movement has to be defined by each application.
- .EO
- .PP
- It is important to understand the correspondence between window features and
- event messages which are sent to the application by the GEM window manager. If
- a feature is not included in a window's creation, the user cannot perform the
- corresponding action, and your application will never receive the matching
- message type. For example, a window without a MOVER may not be dragged by the
- user, and your app will never get a WM_MOVED message for that window.
- .PP
- Another important principle is that the application itself is responsible for
- implementing the user's window action request when a message is received. This
- gives the application a chance to accept, modify, or reject the user's request.
- .PP
- As an example, if a WM_MOVED message is received, it indicates that the user
- has dragged the window. You might want to byte or word align the requested
- position before proceeding to move the window. The wind_set calls used to
- perform the actual movements will be described in the next article.
- .SH OPEN, SESAME!
- The wind_open call is used to actually make the window appear
- on the screen. It animates a "zoom box" on the screen and then draws in the
- window's frame. The calling sequence is:
- .FB wind_open()
- wind_open(handle, x, y, w, h);
- .FE
- The handle is the one returned by wind_create. Parameters x, y, w, and h
- define the initial location and size of the window. Note that these
- measurements INCLUDE all of the window frame parts which you have requested. To
- find out the size of the area inside the frame, you can use
- .FB wind_get()
- wind_get(handle, WF_WXYWH, &inner_x, &inner_y, &inner_w, &inner_h);
- .FE
- Whatever size you choose for the window display, it cannot be any larger than
- the full size declared in wind_create.
- .PP
- Here is a good place to take note of a useful utility for calculating window
- sizes. If you know the "parts list" for a window, and its inner or outer size,
- you can find the other size with the wind_calc call:
- .FB wind_calc()
- wind_calc(parts, kind, input_x, input_y, input_w, input_h, &output_x,
- &output_y, &output_w, &output_h);
- .FE
- Kind is set to zero if the input coordinates are the inner area, and you are
- calculating the outer size. Kind is one if the inputs are the outer size and
- you want the equivalent inner size. Parts are just the same as in wind_create.
- .PP
- There is one common bug in using wind_open. If the NAME feature is
- specified, then the window title must be initialized BEFORE opening the window:
- .FB wind_set()
- wind_set(handle, WF_NAME, ADDR(title), 0, 0);
- .FE
- If you don't do this, you may get gibberish in the NAME area or the system
- may crash. Likewise, if you have specified the INFO feature, you must make a
- wind_set call for WF_INFO before opening the window.
- .PP
- Note that ADDR() specifies the 32-bit address of title. This expression is
- portable to other (Intel-based) GEM systems. If you don't care about
- portability, then &title[0], or just title alone will work fine on the ST.
- .SH CLEANING UP
- When you are done with a window, it should be closed and
- deleted. The call
- .FB wind_close()
- wind_close(handle);
- .FE
- takes the window off the screen, redraws the desktop underneath it,
- and animates a "zoom down" box. It doesn't delete the window's
- definition, so you can reopen it later.
- .PP
- Deleting the window removes its definition from the system, and makes that
- handle available for reuse. Always close windows before deleting, or you may
- leave a "dead" picture on the screen. Also be sure to delete all of your
- windows before ending the program, or your app may "eat" window handles. The
- syntax for deleting a window is:
- .FB wind_delete()
- wind_delete(handle);
- .FE
- .SH THOSE FAT SLIDERS
- One of ST GEM's unique features is the proportional
- slider bar. Unlike other windowing systems, this type of bar gives visual
- feedback on the fraction of a document which is being viewed, as well as the
- position within the document. The catch, of course, is that you have two
- variables to maintain for each scroll bar: size and position.
- .PP
- Both bar size and position range from 1 to 1000. A bar size of 1000 fills
- the slide box, and a value of one gets the minimum bar size. To compute the
- proper size, you can use the formula:
- .br
- .sp 1
- .ce 1
- size = min(1000, 1000 * seen_doc / total_doc)
- .br
- .sp 1
- Seen_doc and total_doc are the visible and total size of the document
- respectively, in whatever units are appropriate. As an example, if your window
- could show 20 lines of a 100 line text file, you should set a slider size of
- 200. Since the window might be bigger than the total document at some points,
- you need the maximum function. If the document size is zero, force the slider
- size to 1000. (Note: You will probably need to do the computation above with
- 32-bit arithmetic to avoid overflow problems).
- .PP
- Once you have computed the size, use the wind_set function to configure the
- scroll bar:
- .FB wind_set()
- wind_set(handle, WF_VSLSIZE, size, 0, 0, 0);
- .FE
- This call sets the vertical (right hand) scroll bar. Use WF_HSLSIZE for the
- horizontal scroller. All of these examples are done for the vertical
- dimension, but the principles are identical in the other direction.
- .PP
- Bar positioning is a little tougher. The most confusing aspect is that the
- 1-1000 range does not set an absolute position of the bar within the
- scroll box. Instead, it positions the TOP of the bar within its
- possible range of variation.
- .PP
- Let's look at our text file example again to make this clearer. If there are
- always 20 lines of a 100 line file visible, then the top of the window must be
- always be somewhere between line 1 and line 81. This 80 line range is
- the actual freedom of movement of the window. So, if the window were
- actually positioned with its top at line 61, it would be at the
- three-quarter position within the range, and we should set a scroll
- bar position of 750. The actual formula for computing the position is:
- .sp 1
- .ce 1
- pos = 1000 * (top_wind - top_doc) / (total_doc - seen_doc)
- .sp 1
- Top_wind and top_doc are the top line in the current window and the whole
- document, respectively. Obviously, if seen_doc is greater or equal to
- total_doc, you need to force a zero value for pos. This calculation may seem
- rather convoluted the first time through, but is easy once you have done it.
- When you have computed the position, wind_set configures the scroll bar:
- .FB wind_set()
- wind_set(handle, WF_VSLIDE, pos, 0, 0, 0);
- .FE
- .sp 1
- .ce 1
- WF_HSLIDE is the equivalent for horizontal scrolling.
- .sp 1
- It is a good practice to avoid setting the slider size or position if they
- are already at the value which you need. This avoids an annoying redraw flash
- on the screen when it is not necessary. You can check on the current
- value of a slider parameter with wind_get:
- .FB wind_get()
- wind_get(handle, WF_VSLIDE, &curr_value, &foo, &foo, &foo);
- .FE
- Foo is a dummy variable which needs to be there, but is not used. Substitute
- WF_VSLIDE with whatever parameter you are checking.
- .PP
- One philosophical note on the use of sliders: It is probably best to avoid
- the use of both sliders at once unless it is clearly appropriate to the type of
- data which is being viewed.
- .PP
- Since Write and Paint programs make use of the sheet-of-paper metaphor,
- moving the window around in both dimensions is reasonable. However, if the data
- is more randomly organized, such as a tableau of icons, then it is probably
- better to only scroll in the vertical dimension and "reshuffle" if
- the window's width is changed. Then the user only needs to manipulate
- one control to find information which is off-screen. Anyone who has
- had trouble finding a file or folder within a Desktop window will
- recognize this problem.
- .SH COMING UP NEXT
- In my next column in Antic Online, we'll conclude the tour of the ST's
- windowing system. I'll discuss the correct way to redraw a window's contents,
- and how to handle the various messages which an application receives from the
- window manager. Finally, we'll look at a way to redesign the desktop
- background to your own specifications.
- .SH FEEDBACK
- One of the beauties of an on-line column is that you can make your comments
- known immediately. To register your opinions, select ST FEEDBACK, enter your
- message, leave your name, and enter a blank line to exit.
- .PP
- I am interested in hearing proposals for topics, feedback on the technical
- level of the column, and reports on bugs and other "features" in both
- the column and the ST itself. Your comments will be read by the ANTIC
- staff and myself and, though we might not answer individual questions,
- they will be used to steer the course of future columns.
- .!
- .!
- .!*****************************************************************************
- .!* *
- .!* End Part 1 *
- .!* *
- .!*****************************************************************************
-